package com.chhuang.utils.httpRequest;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.SSLContext;

import net.sf.json.JSONObject;

import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;

import com.chhuang.utils.file.FileUtil;

/**
 * 
 * @author HuangChen
 * 
 */
public class HttpClientUtil {
	private HttpClientUtil() {
	}

	public static final String HTTPS = "https";
	public static final String APPLICATION_JSON = "application/json";
	public static final String TEXT_PLAIN = "text/plain";

	public static final String SET_COOKIE = "Set-Cookie";
	public static final String CONTENT_TYPE = "Content-Type";
	public static final String CONTENT_LANGUAGE = "Content-Language";

	public static final String QUESTION = "?";
	public static final String AND = "&";
	public static final String POINT = ".";

	public static CloseableHttpClient createSSLClientDefault() {
		try {
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(
					null, new TrustStrategy() {
						public boolean isTrusted(
								java.security.cert.X509Certificate[] arg0,
								String arg1) throws CertificateException {
							return true;
						}
					}).build();
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
					sslContext);
			return HttpClients.custom().setSSLSocketFactory(sslsf).build();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		}
		return HttpClients.createDefault();
	}

	/**
	 * 
	 * @param url
	 * @param params
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public static ResponseBean post(String url,
			List<BasicNameValuePair> params, Header[] headers)
			throws ClientProtocolException, IOException {
		// 创建默认的httpClient实例.
		CloseableHttpClient httpClient = null;
		if (url.toLowerCase().startsWith(HTTPS)) {
			httpClient = createSSLClientDefault();
		} else {
			httpClient = HttpClients.createDefault();
		}
		// 创建httppost
		HttpPost httpPost = new HttpPost(url);
		if (headers != null && headers.length > 0) {
			httpPost.setHeaders(headers);
		}
		if (params != null) {
			httpPost.setEntity(new UrlEncodedFormEntity(params,
					Consts.UTF_8));
		}

		CloseableHttpResponse response = httpClient.execute(httpPost);
		HttpEntity entity = response.getEntity();
		String result = EntityUtils.toString(entity, Consts.UTF_8);
		ResponseBean responseBean = new ResponseBean(response.getAllHeaders(),
				response.getLocale(), response.getProtocolVersion(),
				response.getStatusLine(), result);

		response.close();
		httpClient.close();

		return responseBean;
	}

	/**
	 * 
	 * @param url
	 * @param json
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public static ResponseBean post(String url, JSONObject json,
			Header[] headers) throws ClientProtocolException, IOException {
		// 创建默认的httpClient实例.
		CloseableHttpClient httpClient = null;
		if (url.toLowerCase().startsWith(HTTPS)) {
			httpClient = createSSLClientDefault();
		} else {
			httpClient = HttpClients.createDefault();
		}
		// 创建httppost
		HttpPost httpPost = new HttpPost(url);
		if (headers != null && headers.length > 0) {
			httpPost.setHeaders(headers);
		}
		if (json != null) {
			StringEntity entity = new StringEntity(json.toString(),
					Consts.UTF_8);
			entity.setContentType(APPLICATION_JSON);
			httpPost.setEntity(entity);
		}

		CloseableHttpResponse response = httpClient.execute(httpPost);
		HttpEntity entity = response.getEntity();
		String result = EntityUtils.toString(entity, Consts.UTF_8);
		ResponseBean responseBean = new ResponseBean(response.getAllHeaders(),
				response.getLocale(), response.getProtocolVersion(),
				response.getStatusLine(), result);

		response.close();
		httpClient.close();

		return responseBean;
	}

	/**
	 * 
	 * @param url
	 * @param params
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public static ResponseBean get(String url, List<BasicNameValuePair> params,
			Header[] headers) throws ClientProtocolException, IOException {
		// 创建默认的httpClient实例.
		CloseableHttpClient httpClient = null;
		if (url.toLowerCase().startsWith(HTTPS)) {
			httpClient = createSSLClientDefault();
		} else {
			httpClient = HttpClients.createDefault();
		}
		// 创建httpGet
		HttpGet httpGet = new HttpGet(url);
		if (headers != null && headers.length > 0) {
			httpGet.setHeaders(headers);
		}
		if (params != null) {
			String param = URLEncodedUtils.format(params,
					Consts.UTF_8);
			if (url.lastIndexOf(QUESTION) == -1) {
				url += QUESTION + param;
			} else {
				url += AND + param;
			}
		}

		CloseableHttpResponse response = httpClient.execute(httpGet);
		HttpEntity entity = response.getEntity();
		String result = EntityUtils.toString(entity, Consts.UTF_8);
		ResponseBean responseBean = new ResponseBean(response.getAllHeaders(),
				response.getLocale(), response.getProtocolVersion(),
				response.getStatusLine(), result);

		response.close();
		httpClient.close();

		return responseBean;
	}

	/**
	 * 
	 * @param url
	 * @param parts
	 * @param headers
	 * @return
	 * @throws IOException 
	 * @throws ClientProtocolException 
	 */
	public static ResponseBean upload(String url, Map<String, ContentBody> parts, Header[] headers) 
			throws ClientProtocolException, IOException{
		// 创建默认的httpClient实例.
		CloseableHttpClient httpClient = null;
		if (url.toLowerCase().startsWith(HTTPS)) {
			httpClient = createSSLClientDefault();
		} else {
			httpClient = HttpClients.createDefault();
		}
		
		// 把一个普通参数和文件上传给下面这个地址 是一个servlet
		HttpPost httpPost = new HttpPost(url);
		if (headers != null && headers.length > 0) {
			httpPost.setHeaders(headers);
		}
		if(parts!=null && !parts.isEmpty()){
			MultipartEntityBuilder builder = MultipartEntityBuilder.create().setCharset(Consts.UTF_8);
			Iterator<Entry<String, ContentBody>> iter = parts.entrySet().iterator();
			while (iter.hasNext()) {
				builder.addPart(iter.next().getKey(), iter.next().getValue());
			}
			httpPost.setEntity(builder.build());
		}
		// 发起请求 并返回请求的响应
		CloseableHttpResponse response = httpClient.execute(httpPost);
		HttpEntity entity = response.getEntity();
		String result = EntityUtils.toString(entity, Consts.UTF_8);
		ResponseBean responseBean = new ResponseBean(response.getAllHeaders(),
				response.getLocale(), response.getProtocolVersion(),
				response.getStatusLine(), result);

		// 销毁
		EntityUtils.consume(entity);
		response.close();
		httpClient.close();

		return responseBean;
	}

	/**
	 * 
	 * @param url
	 * @param file
	 * @param headers
	 * @throws IOException 
	 * @throws ClientProtocolException 
	 */
	public static ResponseBean download(String url, File file, Header[] headers) 
			throws ClientProtocolException, IOException{
		// 创建默认的httpClient实例.
		CloseableHttpClient httpClient = null;
		if (url.toLowerCase().startsWith(HTTPS)) {
			httpClient = createSSLClientDefault();
		} else {
			httpClient = HttpClients.createDefault();
		}
		HttpGet httpGet = new HttpGet(url);
		if (headers != null && headers.length > 0) {
			httpGet.setHeaders(headers);
		}
		// 发起请求 并返回请求的响应
		CloseableHttpResponse response = httpClient.execute(httpGet);
		HttpEntity entity = response.getEntity();
		ResponseBean responseBean = new ResponseBean(response.getAllHeaders(),
				response.getLocale(), response.getProtocolVersion(),
				response.getStatusLine(), null);
		
		InputStream in = entity.getContent();
		FileUtil.makeFilePath(file);
		FileOutputStream fout = new FileOutputStream(file);
		int l = -1;
		byte[] tmp = new byte[4096];
		while ((l = in.read(tmp)) != -1) {
			fout.write(tmp, 0, l);
		}
		fout.flush();
		fout.close();
		in.close();
		response.close();
		httpClient.close();
		
		return responseBean;
	}
}